package hr.fer.zpr.nmbp.project3.dao;

import hr.fer.zpr.nmbp.project3.dao.exceptions.DAOException;
import hr.fer.zpr.nmbp.project3.dao.exceptions.PrimaryKeyConstraintException;
import hr.fer.zpr.nmbp.project3.dao.util.ObjectFromXMLGen;
import hr.fer.zpr.nmbp.project3.dao.util.XMLGen;
import hr.fer.zpr.nmbp.project3.model.Pacijent;

import java.util.ArrayList;
import java.util.List;

import org.exist.xmldb.XQueryService;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;

public class PacijentDAO {
	
	private XQueryService xqs;

	public PacijentDAO(Collection col) {
		try {
			this.xqs = (XQueryService)col.getService("XQueryService", "1.0");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom");
		}
	}

	public void save(Pacijent pacijent) {
		if(pacijent.getMbo() == 0){
			throw new PrimaryKeyConstraintException("MBO je obavezan");
		}
		
		// Update pacijenta ako postoji u bazi
    	try {
			if(this.exists(pacijent)) {
				throw new PrimaryKeyConstraintException("MBO već postoji");
			}
    	
			// Spremanje nove bolnice u bazu
			xqs.query("update insert " + XMLGen.getXML(pacijent) + "into /ebolnica/pacijenti");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
	}

	public void update(Pacijent pacijent) {
	
		// Ažuriranje pacijenta
    	try {
    		if(!this.exists(pacijent)) {
    			return;
    		}
    		
			xqs.query("update replace /ebolnica/pacijenti/pacijent[@mbo=" + pacijent.getMbo() + "] " +
					"with " + XMLGen.getXML(pacijent));
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
	}

	private boolean exists(Pacijent pacijent) throws XMLDBException {
    	ResourceSet set = xqs.query("/ebolnica/pacijenti/pacijent[@mbo="+pacijent.getMbo()+"]");
    	if(set.getSize() > 0){
    		return true;
    	}else{
    		return false;
    	}
	}

	public void delete(Pacijent pacijent) {		
    	try {
    		// Brisanje stranih ključeva u dijagnozi
    		xqs.query("for $d in /ebolnica/pacijenti/pacijent[@mbo="+ pacijent.getMbo() +"]" +
    				"/karton/dijagnoza return update delete " +
    				"/ebolnica//dijagnozaBolest[@dijagnoza=data($d/@sifra)]");
    		
    		// Brisanje pacijenta
			xqs.query("update delete /ebolnica/pacijenti/pacijent[@mbo=" +
					pacijent.getMbo() + "]");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
	}

    
	public List<Pacijent> load(Pacijent pacijentPrototype) {
		List<Pacijent> allPacijenti = this.loadAll();
    	List<Pacijent> filteredPacijenti = new ArrayList<Pacijent>();
    	
    	for(Pacijent pacijent : allPacijenti){
    		if(pacijent.getMbo() == pacijentPrototype.getMbo()){
    			filteredPacijenti.add(pacijent);
    		}
    	}
    	
    	return filteredPacijenti;
	}

	public List<Pacijent> loadAll() {
		ArrayList<Pacijent> loadedPacijenti = new ArrayList<Pacijent>();
    	
    	// Učitavanje pacijenata
    	try {
    		ResourceSet resSet = xqs.query("/ebolnica/pacijenti/pacijent");

    		ResourceIterator iter = resSet.getIterator();
			while(iter.hasMoreResources()){
				XMLResource res = (XMLResource) iter.nextResource();
				Pacijent tempPacijent = (Pacijent)ObjectFromXMLGen.createInstance(res.getContentAsDOM());
				if(tempPacijent != null){
					loadedPacijenti.add(tempPacijent);
				}
			}
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
    	
    	return loadedPacijenti;
	}
}
